package com.gla.giliair.web.customer;

import com.gla.giliair.entity.Customer;
import com.gla.giliair.util.*;
import com.gla.giliair.web.BaseController;
import com.gla.giliair.web.vo.CustomerVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

/**
 * @Description:
 * @Author: Yingtian qian
 * @Date: 2021/8/23 14:36
 */

@Api(tags = "用户模块")
@RestController
@RequestMapping("/api")
public class UserController extends BaseController {

    @ApiOperation(value = "注册", notes = "先发验证码，再注册，手机/邮箱注册二选一", produces = "application/json")
    @PostMapping("/register")
    public Map<String, Object> register(@RequestParam("username") String username,
                                        @RequestParam("password") String password,
                                        @RequestParam("verifyCode") String verifyCode,
                                        //选择邮箱注册还是手机注册：false -> 邮箱, true -> 手机
                                        @RequestParam(value = "isPhone", defaultValue = "false") boolean isPhone,
                                        @RequestParam(value = "phone", required = false) String phone,
                                        @RequestParam(value = "email", required = false) String email,
                                        HttpSession httpSession) {
        if (!StringUtils.hasText(username)) {
            return MapGenerator.getRes(500, "请输入用户名！");
        }
        if (!StringUtils.hasText(password)) {
            return MapGenerator.getRes(501, "请输入密码！");
        }
        if (!StringUtils.hasText(verifyCode)) {
            return MapGenerator.getRes(502, "请输入验证码！");
        }
        if (isPhone) {
            if (!StringUtils.hasText(phone)) {
                return MapGenerator.getRes(503, "请输入手机号！");
            }
            if (!PatternUtil.isPhone(phone)) {
                return MapGenerator.getRes(504, "手机号格式有误！");
            }

            Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");
            //输入的手机号不匹配验证码发送的手机号，等于没发到输入的手机号
            if (rightCode == null || !phone.equals(rightCode.get("identity"))) {
                return MapGenerator.getRes(505, "未发送验证码！");
            }
            if (!verifyCode.equals(rightCode.get("code"))) {
                return MapGenerator.getRes(506, "验证码错误！");
            }
        } else {
            if (!StringUtils.hasText(email)) {
                return MapGenerator.getRes(507, "请输入邮箱！");
            }
            if (!PatternUtil.isEmail(email)) {
                return MapGenerator.getRes(508, "邮箱格式有误！");
            }

            Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");
            if (rightCode == null || !email.equals(rightCode.get("identity"))) {
                return MapGenerator.getRes(505, "未发送验证码！");
            }
            if (!verifyCode.equals(rightCode.get("code"))) {
                return MapGenerator.getRes(506, "验证码错误！");
            }
        }

        Customer user = new Customer();
        user.setUsername(username);
        user.setPassword(MD5Util.md5Encode(password));
        if (isPhone) {
            user.setPhone(phone);
        } else {
            user.setEmail(email);
        }

        Map<String, Object> res = userService.registerUser(user);
        //注册成功，删除session中的verifyCode
        if ((Integer) res.get("status") == 200) {
            httpSession.removeAttribute("verifyCode");
        }
        return res;
    }

    @ApiOperation(value = "获取验证码", notes = "发送验证码，手机/邮箱验证码二选一", produces = "application/json")
    @PostMapping("/sendCode")
    @ResponseBody
    public Map<String, Object> sendCode(//选择发邮箱验证码还是手机验证码：false -> 邮箱, true -> 手机
                                        @RequestParam(value = "isPhone", defaultValue = "false") boolean isPhone,
                                        @RequestParam(value = "phone", required = false) String phone,
                                        @RequestParam(value = "email", required = false) String email,
                                        HttpSession httpSession) {
        if (isPhone) {
            if (!StringUtils.hasText(phone)) {
                return MapGenerator.getRes(500, "请输入手机号！");
            }
            if (!PatternUtil.isPhone(phone)) {
                return MapGenerator.getRes(501, "手机号格式有误！");
            }

            String code = EmailUtil.createSimpleCode();
            System.out.println("手机验证码：" + code);
            int time = 3;
            //需要存Map，只存验证码会被钻漏洞
            httpSession.setAttribute("verifyCode", MapGenerator.getCode(phone, code));
            //有效期3分钟
            httpSession.setMaxInactiveInterval(60 * time);
            try {
                SMSUtil.sendSMS(code, phone, time);
            } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
                e.printStackTrace();
            }
        } else {
            if (!StringUtils.hasText(email)) {
                return MapGenerator.getRes(502, "请输入邮箱！");
            }
            if (!PatternUtil.isEmail(email)) {
                return MapGenerator.getRes(503, "邮箱格式有误！");
            }

            String code = EmailUtil.createSimpleCode();
            int time = 3;
            System.out.println("邮箱验证码：" + code);
            httpSession.setAttribute("verifyCode", MapGenerator.getCode(email, code));
            httpSession.setMaxInactiveInterval(60 * time);
            EmailUtil.sendCodeEmail(code, email, time);
        }
        return MapGenerator.getRes(200, "发送成功！");
    }

    @ApiOperation(value = "登录", notes = "登录", produces = "application/json")
    @PostMapping("/loginIn")
    @ResponseBody
    public Map<String, Object> loginIn(@RequestParam("username") String username,
                                       @RequestParam("password") String password,
                                       HttpSession httpSession) {
        if (!StringUtils.hasText(username)) {
            return MapGenerator.getRes(500, "请输入用户名！");
        }
        if (!StringUtils.hasText(password)) {
            return MapGenerator.getRes(501, "请输入密码！");
        }
        return userService.checkLogin(username, MD5Util.md5Encode(password), httpSession);
    }

    @ApiOperation(value = "登出", notes = "登出", produces = "application/json")
    @PostMapping("/user/loginOut")
    @ResponseBody
    public Map<String, Object> loginOut(HttpSession httpSession) {
        httpSession.removeAttribute("user");
        return MapGenerator.getRes(200, "用户登出成功！");
    }

    @ApiOperation(value = "获取已登录的用户信息", notes = "从session中拿取用户VO", produces = "application/json")
    @GetMapping("/user/getInfo")
    @ResponseBody
    public Map<String, Object> getInfo(HttpSession httpSession) {
        CustomerVO userTemp = (CustomerVO) httpSession.getAttribute("user");
        System.out.println(httpSession);
        if (userTemp != null) {
            return MapGenerator.getResWithData(200, "获取用户信息成功！", userTemp);
        } else {
            return MapGenerator.getRes(500, "未登录！");
        }
    }

    @ApiOperation(value = "更新用户信息", notes = "登录后才可调用；更新用户生日/性别等文字信息，有效信息只包括：昵称、性别、身份证号、真名、生日、电话、邮箱；身份证和真名要同时修改", produces = "application/json")
    @PostMapping("/user/updateInfo")
    @ResponseBody
    public Map<String, Object> updateInfo(@RequestBody CustomerVO userVO,
                                          HttpSession httpSession) {
        //过滤部分其他有效参数
        userVO.setPhone(null);
        userVO.setEmail(null);

        CustomerVO userVORes = userService.updateUserInfo(userVO, httpSession);
        if (userVORes == null) {
            return MapGenerator.getRes(500, "更新用户信息失败，请检查传入参数！");
        } else {
            return MapGenerator.getResWithData(200, "更新用户信息成功！", userVORes);
        }
    }

    @ApiOperation(value = "重置密码", notes = "先发验证码，再重置密码", produces = "application/json")
    @PostMapping("/resetPassword")
    @ResponseBody
    public Map<String, Object> resetPassword(@RequestParam("password") String password,
                                             @RequestParam("verifyCode") String verifyCode,
                                             HttpSession httpSession) {
        if (!StringUtils.hasText(password)) {
            return MapGenerator.getRes(500, "请输入密码！");
        }
        if (!StringUtils.hasText(verifyCode)) {
            return MapGenerator.getRes(501, "请输入验证码！");
        }

        Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");

        if (rightCode == null) {
            return MapGenerator.getRes(502, "未发送验证码！");
        }
        if (!verifyCode.equals(rightCode.get("code"))) {
            return MapGenerator.getRes(503, "验证码错误！");
        }

        String identity = (String) rightCode.get("identity");

        Customer user = new Customer();
        user.setPassword(MD5Util.md5Encode(password));
        if (PatternUtil.isEmail(identity)) {
            user.setEmail(identity);
        } else {
            user.setPhone(identity);
        }
        //更改密码
        Map<String, Object> res = userService.resetUserPassword(user);

        //重置密码成功，删除session中的verifyCode
        if ((Integer) res.get("status") == 200) {
            httpSession.removeAttribute("verifyCode");
        }
        return res;
    }

    @ApiOperation(value = "验证已有邮箱/手机号", notes = "登录后才可调用；先发验证码，再验证已有邮箱/手机号，之后可在15分钟内自由修改一次手机或邮箱", produces = "application/json")
    @PostMapping("/user/verify")
    @ResponseBody
    public Map<String, Object> verify(@RequestParam("verifyCode") String verifyCode,
                                      HttpSession httpSession) {
        if (!StringUtils.hasText(verifyCode)) {
            return MapGenerator.getRes(500, "请输入验证码！");
        }
        //验证验证码
        Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");

        if (rightCode == null) {
            return MapGenerator.getRes(501, "未发送验证码！");
        }
        if (!verifyCode.equals(rightCode.get("code"))) {
            return MapGenerator.getRes(502, "验证码错误！");
        }

        String identity = (String) rightCode.get("identity");

        //从session中拿的userVO，只要其中的userId（必须登录后才能拿）
        CustomerVO userTemp = (CustomerVO) httpSession.getAttribute("user");

        if (!userService.isIdentityExist(identity, userTemp.getCustomerId())) {
            return MapGenerator.getRes(503, "用户不存在！");
        }

        httpSession.setAttribute("verified", true);
        httpSession.setMaxInactiveInterval(60 * 15);
        httpSession.removeAttribute("verifyCode");

        return MapGenerator.getRes(200, "验证通过！");
    }

    @ApiOperation(value = "修改邮箱", notes = "登录后才可调用；通过验证后可修改一次邮箱", produces = "application/json")
    @PostMapping("/user/resetEmail")
    @ResponseBody
    public Map<String, Object> resetEmail(@RequestParam("newEmail") String newEmail,
                                          @RequestParam("verifyCode") String verifyCode,
                                          HttpSession httpSession) {
        if (!StringUtils.hasText(newEmail)) {
            return MapGenerator.getRes(500, "请输入邮箱！");
        }
        if (!PatternUtil.isEmail(newEmail)) {
            return MapGenerator.getRes(501, "邮箱格式有误！");
        }
        if (!StringUtils.hasText(verifyCode)) {
            return MapGenerator.getRes(502, "请输入验证码！");
        }
        //验证验证码
        Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");
        Boolean isVerified = (Boolean) httpSession.getAttribute("verified");

        if (isVerified == null) {
            return MapGenerator.getRes(503, "未通过验证，不能修改！");
        }
        if (rightCode == null || !newEmail.equals(rightCode.get("identity"))) {
            return MapGenerator.getRes(504, "未发送验证码！");
        }
        if (!verifyCode.equals(rightCode.get("code"))) {
            return MapGenerator.getRes(505, "验证码错误！");
        }

        CustomerVO userVO = new CustomerVO();
        userVO.setEmail(newEmail);
        CustomerVO userVORes = userService.updateUserInfo(userVO, httpSession);

        if (userVORes == null) {
            return MapGenerator.getRes(506, "邮箱已被使用！");
        } else {
            httpSession.removeAttribute("verifyCode");
            httpSession.removeAttribute("verified");
            return MapGenerator.getResWithData(200, "修改邮箱成功！", userVORes);
        }
    }

    @ApiOperation(value = "修改手机号", notes = "登录后才可调用；通过验证后可修改一次手机号", produces = "application/json")
    @PostMapping("/user/resetPhone")
    @ResponseBody
    public Map<String, Object> resetPhone(@RequestParam("newPhone") String newPhone,
                                          @RequestParam("verifyCode") String verifyCode,
                                          HttpSession httpSession) {
        if (!StringUtils.hasText(newPhone)) {
            return MapGenerator.getRes(500, "请输入手机号！");
        }
        if (!PatternUtil.isPhone(newPhone)) {
            return MapGenerator.getRes(501, "手机号格式有误！");
        }
        if (!StringUtils.hasText(verifyCode)) {
            return MapGenerator.getRes(502, "请输入验证码！");
        }
        //验证验证码
        Map<String, Object> rightCode = (Map<String, Object>) httpSession.getAttribute("verifyCode");
        Boolean isVerified = (Boolean) httpSession.getAttribute("verified");

        if (isVerified == null) {
            return MapGenerator.getRes(503, "未通过验证，不能修改！");
        }
        if (rightCode == null || !newPhone.equals(rightCode.get("identity"))) {
            return MapGenerator.getRes(504, "未发送验证码！");
        }
        if (!verifyCode.equals(rightCode.get("code"))) {
            return MapGenerator.getRes(505, "验证码错误！");
        }

        CustomerVO userVO = new CustomerVO();
        userVO.setPhone(newPhone);
        CustomerVO userVORes = userService.updateUserInfo(userVO, httpSession);

        if (userVORes == null) {
            return MapGenerator.getRes(506, "手机已被使用！");
        } else {
            httpSession.removeAttribute("verifyCode");
            httpSession.removeAttribute("verified");
            return MapGenerator.getResWithData(200, "修改手机成功！", userVORes);
        }

    }
}
